#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
条码反向解析器
从二进制条码字符串反推项目编号和批次
"""

from barcode_generator import find_valid_15bit_number, verify_15bit_condition

def decode_barcode_to_encoded(barcode_str):
    """
    将最终条码反向解析为编码字符串
    
    规则：
    - "11" → 'A'
    - "00" → 'B'  
    - "1" → 'C'
    - "0" → 'D'
    
    Args:
        barcode_str (str): 二进制条码字符串
    
    Returns:
        str: 编码字符串，失败返回None
    """
    if not barcode_str or not all(c in '01' for c in barcode_str):
        return None
    
    encoded = ""
    i = 0
    
    while i < len(barcode_str):
        if i + 1 < len(barcode_str):
            # 检查两位模式
            two_bits = barcode_str[i:i+2]
            if two_bits == "11":
                encoded += 'A'
                i += 2
                continue
            elif two_bits == "00":
                encoded += 'B'
                i += 2
                continue
        
        # 单位模式
        if barcode_str[i] == '1':
            encoded += 'C'
        else:  # barcode_str[i] == '0'
            encoded += 'D'
        i += 1
    
    return encoded

def decode_encoded_to_binary(encoded_str):
    """
    将编码字符串反向解析为15位二进制字符串
    
    规则：
    - 偶数位置: 'A'→'1', 'C'→'0'
    - 奇数位置: 'B'→'1', 'D'→'0'
    
    Args:
        encoded_str (str): 编码字符串
    
    Returns:
        str: 15位二进制字符串，失败返回None
    """
    if not encoded_str or len(encoded_str) != 15:
        return None
    
    binary_str = ""
    for i, char in enumerate(encoded_str):
        if i % 2 == 0:  # 偶数位置
            if char == 'A':
                binary_str += '1'
            elif char == 'C':
                binary_str += '0'
            else:
                return None  # 偶数位置只能是A或C
        else:  # 奇数位置
            if char == 'B':
                binary_str += '1'
            elif char == 'D':
                binary_str += '0'
            else:
                return None  # 奇数位置只能是B或D
    
    return binary_str

def binary_to_number(binary_str):
    """
    将15位二进制字符串转换为数字
    
    Args:
        binary_str (str): 15位二进制字符串
    
    Returns:
        int: 对应的数字
    """
    if not binary_str or len(binary_str) != 15:
        return None
    
    try:
        return int(binary_str, 2)
    except ValueError:
        return None

def find_barcode_number_by_15bit(target_number):
    """
    根据15位数查找对应的条码编号
    
    Args:
        target_number (int): 目标15位数
    
    Returns:
        int: 条码编号，未找到返回None
    """
    if target_number < 0 or target_number >= 0x8000:
        return None
    
    # 验证这个数字是否满足条件
    is_valid, _ = verify_15bit_condition(target_number)
    if not is_valid:
        return None
    
    # 查找这是第几个满足条件的数字
    count = 0
    for num in range(target_number + 1):
        is_valid, _ = verify_15bit_condition(num)
        if is_valid:
            count += 1
            if num == target_number:
                return count
    
    return None

def barcode_number_to_project_batch(barcode_number):
    """
    将条码编号转换为项目编号和批次

    Args:
        barcode_number (int): 条码编号

    Returns:
        tuple: (项目编号, 批次)，失败返回None
    """
    if barcode_number < 1 or barcode_number > 4800:  # 80*60 = 4800
        return None

    # 反向计算
    # 条码编号 = (项目编号-1) * 60 + 批次
    # 所以：项目编号 = ((条码编号-1) // 60) + 1
    #      批次 = ((条码编号-1) % 60) + 1

    project_id = ((barcode_number - 1) // 60) + 1
    batch_id = ((barcode_number - 1) % 60) + 1

    # 验证范围
    if 1 <= project_id <= 80 and 1 <= batch_id <= 60:
        return (project_id, batch_id)

    return None

def decode_barcode(barcode_str, verbose=False):
    """
    完整的条码解析过程
    
    Args:
        barcode_str (str): 二进制条码字符串
        verbose (bool): 是否显示详细过程
    
    Returns:
        tuple: (项目编号, 批次)，失败返回None
    """
    if verbose:
        print(f"=== 条码反向解析: {barcode_str} ===")
        print(f"条码长度: {len(barcode_str)}")
    
    # 步骤1：解析为编码字符串
    encoded_str = decode_barcode_to_encoded(barcode_str)
    if not encoded_str:
        if verbose:
            print("错误：无法解析为编码字符串")
        return None
    
    if verbose:
        print(f"步骤1 - 解析为编码字符串: {encoded_str}")
    
    # 步骤2：解析为15位二进制
    binary_str = decode_encoded_to_binary(encoded_str)
    if not binary_str:
        if verbose:
            print("错误：无法解析为15位二进制字符串")
        return None
    
    if verbose:
        print(f"步骤2 - 15位二进制: {binary_str}")
    
    # 步骤3：转换为数字
    number = binary_to_number(binary_str)
    if number is None:
        if verbose:
            print("错误：无法转换为数字")
        return None
    
    if verbose:
        print(f"步骤3 - 15位数: {number} (0x{number:04X})")
    
    # 验证数字是否满足条件
    is_valid, counts = verify_15bit_condition(number)
    if not is_valid:
        if verbose:
            print(f"错误：数字不满足条件 (组计数: {counts})")
        return None
    
    if verbose:
        print(f"步骤4 - 验证条件: 组1={counts[0]}, 组2={counts[1]}, 组3={counts[2]}, 总和={counts[3]} ✓")
    
    # 步骤4：查找条码编号
    barcode_number = find_barcode_number_by_15bit(number)
    if barcode_number is None:
        if verbose:
            print("错误：无法找到对应的条码编号")
        return None
    
    if verbose:
        print(f"步骤5 - 条码编号: {barcode_number}")
    
    # 步骤5：计算项目编号和批次
    result = barcode_number_to_project_batch(barcode_number)
    if result is None:
        if verbose:
            print("错误：无法计算项目编号和批次")
        return None
    
    project_id, batch_id = result
    if verbose:
        print(f"步骤6 - 项目编号: {project_id}, 批次: {batch_id}")
    
    return (project_id, batch_id)

def verify_decode_result(barcode_str, project_id, batch_id):
    """
    验证解析结果的正确性
    
    Args:
        barcode_str (str): 原始条码字符串
        project_id (int): 解析出的项目编号
        batch_id (int): 解析出的批次
    
    Returns:
        bool: 验证是否通过
    """
    from barcode_generator import generate_barcode
    
    # 重新生成条码
    regenerated_barcode = generate_barcode(project_id, batch_id)
    
    # 比较结果
    return regenerated_barcode == barcode_str

def batch_test_decoder():
    """批量测试解析器的正确性"""
    from barcode_generator import generate_barcode
    
    print("=== 批量测试条码解析器 ===\n")
    
    test_cases = [
        (1, 1),
        (2, 1),
        (1, 2),
        (80, 60),
        (10, 5),
        (25, 30),
        (50, 45),
    ]
    
    success_count = 0
    total_count = len(test_cases)
    
    for original_project, original_batch in test_cases:
        print(f"测试: 项目{original_project}, 批次{original_batch}")
        
        # 生成条码
        barcode = generate_barcode(original_project, original_batch)
        if not barcode:
            print("  错误：无法生成条码")
            continue
        
        print(f"  生成条码: {barcode}")
        
        # 解析条码
        result = decode_barcode(barcode)
        if not result:
            print("  错误：解析失败")
            continue
        
        decoded_project, decoded_batch = result
        print(f"  解析结果: 项目{decoded_project}, 批次{decoded_batch}")
        
        # 验证结果
        if decoded_project == original_project and decoded_batch == original_batch:
            print("  ✓ 解析正确")
            success_count += 1
        else:
            print("  ✗ 解析错误")
        
        print()
    
    print(f"测试结果: {success_count}/{total_count} 通过")
    return success_count == total_count

def interactive_decoder():
    """交互式解析器"""
    print("=== 交互式条码解析器 ===")
    print("输入条码字符串进行解析，输入 'quit' 退出\n")
    
    while True:
        try:
            user_input = input("请输入条码字符串: ").strip()
            
            if user_input.lower() in ['quit', 'q', 'exit']:
                break
            
            if not user_input:
                continue
            
            if not all(c in '01' for c in user_input):
                print("错误：条码字符串只能包含0和1")
                continue
            
            print(f"\n解析条码: {user_input}")
            result = decode_barcode(user_input, verbose=True)
            
            if result:
                project_id, batch_id = result
                print(f"\n✓ 解析成功!")
                print(f"项目编号: {project_id}")
                print(f"批次: {batch_id}")
                
                # 验证结果
                if verify_decode_result(user_input, project_id, batch_id):
                    print("✓ 验证通过")
                else:
                    print("✗ 验证失败")
            else:
                print("\n✗ 解析失败")
            
            print("\n" + "="*50 + "\n")
            
        except KeyboardInterrupt:
            break
        except Exception as e:
            print(f"错误: {e}")
    
    print("再见！")

def main():
    """主函数"""
    import sys

    if len(sys.argv) == 2:
        # 直接解析指定的条码
        barcode_str = sys.argv[1]
        print(f"解析条码: {barcode_str}")
        result = decode_barcode(barcode_str, verbose=True)
        if result:
            project_id, batch_id = result
            print(f"\n✓ 解析成功!")
            print(f"项目编号: {project_id}")
            print(f"批次: {batch_id}")

            # 验证结果
            if verify_decode_result(barcode_str, project_id, batch_id):
                print("✓ 验证通过")
            else:
                print("✗ 验证失败")
        else:
            print("\n✗ 解析失败")
    elif len(sys.argv) == 1:
        # 运行测试和交互模式
        if batch_test_decoder():
            print("\n所有测试通过！\n")
        else:
            print("\n部分测试失败！\n")

        interactive_decoder()
    else:
        print("用法:")
        print("  python barcode_decoder.py                    # 运行测试和交互模式")
        print("  python barcode_decoder.py <条码字符串>        # 直接解析条码")
        print("\n示例:")
        print("  python barcode_decoder.py 101010101001100110011")

if __name__ == "__main__":
    main()
